package poo.recursion;

import poo.util.*;

public class TorriDiHanoi {

	private static enum Pin {
		SX, CL, DX
	};

	public void sposta1Disco(Pin da, Pin a) {
		System.out.println("Sposta un disco da " + da + " a " + a);
	}// Sposta1Disco

	public void muovi(int n, Pin sorg, Pin aus, Pin dest) {
		if (n == 1)
			sposta1Disco(sorg, dest);
		else {
			muovi(n - 1, sorg, dest, aus);
			sposta1Disco(sorg, dest);
			muovi(n - 1, aus, sorg, dest);
		}
	}// muovi

	public void muovi_ite(int nd, Pin src, Pin aux, Pin dst) {

		class AreaDati {
			int n;
			Pin sorg, aus, dest;

			public AreaDati() {
				this.n = nd;
				this.sorg = src;
				this.aus = aux;
				this.dest = dst;
			}

			public AreaDati(int n, Pin sorg, Pin aus, Pin dest) {
				this.n = n;
				this.sorg = sorg;
				this.aus = aus;
				this.dest = dest;
			}
		}// AreaDati

		Stack<AreaDati> pila = new StackConcatenato<AreaDati>();

		pila.push(new AreaDati());
		AreaDati ad = null;
		while (!pila.isEmpty()) {
			ad = pila.pop(); // area dati corrente
			if (ad.n == 1)
				sposta1Disco(ad.sorg, ad.dest);
			else {// simulazione chiamate ricorsive
				pila.push(new AreaDati(ad.n - 1, ad.aus, ad.sorg, ad.dest));
				pila.push(new AreaDati(1, ad.sorg, ad.aus, ad.dest));
				pila.push(new AreaDati(ad.n - 1, ad.sorg, ad.dest, ad.aus));
			}
		}// while

	}// muovi_ite

	public static void main(String[] args) {
		// new TorriDiHanoi().muovi(3, Pin.SX, Pin.CL, Pin.DX ); //ricorsione
		new TorriDiHanoi().muovi_ite(3, Pin.SX, Pin.CL, Pin.DX); // iterazione
	}// main
}// TorriDiHanoi
